#ifndef INTERMEDIATECODE_H_
#define INTERMEDIATECODE_H_

#include <string>
#include <vector>
#include "Interfaces.h"
#include "FunctionEntry.h"
#include "ThreeAddressCode.h"
#include <ext/hash_map>
#include "HashMapStringFix.h"
#include "MoonGenerator.h"

#define DEBUG_INT_CODE 0

typedef std::vector<ThreeAddressCode> ICodeRep;
typedef HASH_MAP_NAMESPACE::hash_map<std::string, int> FunctionSizeMap;
typedef std::pair<std::string, int> FSizePair;

class IntermediateCode : public FunctionObserver, public ICodeInterface, public TCodeInterface
{
public:
	IntermediateCode();
	virtual ~IntermediateCode();

	void threeAddressCode(attr result, OpCode opCode, int index);
	void threeAddressCode(attr result, OpCode opCode, attr operand);
	void threeAddressCode(attr result, OpCode opCode, attr operand1, attr operand2);
	void threeAddressCode(attr result, OpCode opCode, std::string callLabel, int paramCount);
	void threeAddressCode(int addtress, OpCode opCode, std::string callLabel, int paramCount);
	
	void threeAddressCode(std::string label);
		
	void threeAddressCode(OpCode opCode);
	void threeAddressCode(OpCode opCode, attr operand);
	void threeAddressCode(OpCode opCode, attr operand, std::string gotoLabel);

	void threeAddressCode(OpCode opCode, std::string label);
	void threeAddressCode(OpCode opCode, ParamList* pList);

	std::string getNextLabel();
	
	bool hasNextTAC();
	const ThreeAddressCode* nextTAC();
	int getFunctionSize(std::string functionLabel);
	
	void updateFunction(std::string label, int size);
	
private:
	ICodeRep iCodeRepository;
	FunctionSizeMap fSize;
	
	int currentTAC;
	int labelCounter;
	std::string label;
	bool applyLabel;
		
	void addTAC(ThreeAddressCode tac);
	void setLabel(ThreeAddressCode &tac);
};

#endif /*INTERMEDIATECODE_H_*/
